package cn.changeforyou.tcpIp.analysis.demo.datastructs;

import java.time.LocalDateTime;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;

/**
 * 16进制的String字符串读取工具类
 *
 * @author zhyu
 * @date 2020/8/7 14:11
 */
public class HexStringReadBuffer {

    private char[] chars;

    private int pos;

    private int size;

    static char[] empty = "".toCharArray();

    public boolean avialable() {
        return pos < size - 1;
    }

    /**
     * 读取时间
     *
     * @return
     */
    public LocalDateTime readDatetime() {
        byte year = Byte.parseByte(readHexString(2), 16);
        byte month = Byte.parseByte(readHexString(2), 16);
        byte day = Byte.parseByte(readHexString(2), 16);
        byte hour = Byte.parseByte(readHexString(2), 16);
        byte minute = Byte.parseByte(readHexString(2), 16);
        byte second = Byte.parseByte(readHexString(2), 16);
        return LocalDateTime.of(2000 + year, month, day, hour, minute, second);
    }

    /**
     * 读取short
     *
     * @return
     */
    public short readShort() {
        return Short.parseShort(readHexString(4), 16);
    }

    /**
     * 读取一定长度的普通字符串
     *
     * @param length
     * @return
     * @throws DecoderException
     */
    public String readString(int length) throws DecoderException {
        char[] chars = readCharsWithoutException(length);
        byte[] bytes = Hex.decodeHex(chars);
        return new String(bytes);
    }

    /**
     * 读出一定长度的16进制字符串
     *
     * @param length
     * @return
     */
    public String readHexString(int length) {
        char[] chars = readChars(length);
        return new String(chars);
    }

    /**
     * 读取char
     *
     * @param length
     * @return
     */
    private char[] readChars(int length) {
        if (0 == size) {
            throw new IndexOutOfBoundsException();
        }

        if (pos + length > size) {
            throw new IndexOutOfBoundsException();
        }
        char[] charss = new char[length];
        System.arraycopy(chars, pos, charss, 0, length);
        pos += length;
        return charss;
    }

    /**
     * 读取char不会抛出异常
     *
     * @param length
     * @return
     */
    private char[] readCharsWithoutException(int length) {
        if (0 == size) {
            return empty;
        }
        char[] charss;
        int expected = pos + length;
        if (expected > size) {
            charss = new char[size - (expected)];
            System.arraycopy(chars, pos, charss, 0, size - (expected));
        } else {
            charss = new char[length];
            System.arraycopy(chars, pos, charss, 0, length);

        }
        pos = expected;
        return charss;
    }

    public HexStringReadBuffer(String str) {
        if (null == str) {
            chars = new char[1];
            size = 0;
        } else {
            chars = new char[str.length()];
            str.getChars(0, str.length(), chars, 0);
            size = str.length();
        }
    }

    public HexStringReadBuffer(char[] charss) {
        if (null == charss) {
            chars = new char[1];
            size = 0;
        } else {
            chars = charss;
            size = charss.length;
        }
    }

    /**
     * 取出short值 用String包装, 当遇到的16进制值为已知值时, 返回16进制的该值
     *
     * @param strs
     * @return
     */
    public String readShortExcept(String... strs) {
        char[] chars = readChars(4);
        String string = new String(chars);
        if (null != strs && strs.length > 0) {
            for (String str : strs) {
                if (str.equals(string)) {
                    return str;
                }
            }
        }
        return String.valueOf(Short.parseShort(string, 16));
    }

    /**
     * 取出short值 用String包装, 当遇到的16进制值为已知值时, 返回16进制的该值
     *
     * @param strs
     * @return
     */
    public String readIntExcept(String... strs) {
        char[] chars = readChars(8);
        String string = new String(chars);
        if (null != strs && strs.length > 0) {
            for (String str : strs) {
                if (str.equals(string)) {
                    return str;
                }
            }
        }
        return String.valueOf(Integer.parseInt(string, 16));
    }

    /**
     * 取出short值 用String包装, 当遇到的16进制值为已知值时, 返回16进制的该值
     *
     * @param strs
     * @return
     */
    public String readByteExcept(String... strs) {
        char[] chars = readChars(8);
        String string = new String(chars);
        if (null != strs && strs.length > 0) {
            for (String str : strs) {
                if (str.equals(string)) {
                    return str;
                }
            }
        }
        return String.valueOf(Byte.parseByte(string, 16));
    }
}
